Bug in gethostbyaddr() on some systems

Jon Peatfield (J.S.Peatfield@amtp.cam.ac.uk)
Wed, 01 Mar 1995 16:05:32 +0000

I've sent this information to HP's security team and passed it onto our local 
DEC contact.  I don't know how many other machines are affected, (not Irix 
5.2, Solaris-2.3, SunOS4 as far as I can tell).

Both DECs (OSF/1 1.3, 2.0, 3.0) and HPs (if you apply certain libc patches 
(e.g. PHCO_5153 etc) to get nsswitch.conf stuff) have a bug in gethostbyaddr() 
if you have set the search order in nsswitch.conf/svc.conf to 
files,dns/local,bind.  That is if you have set the resolver code to look in 
the /etc/hosts file first and then go on to look in the DNS for results.  
Other orders may also have bugs I've not investigated this.

The bug causes the h_aliases field of the hostent struct to get filled in with 
stuff from the last valid line in your /etc/hosts rather than whatever it 
should get.

This is a security hole for things which look at this information to decide 
who a machine it.  At least HP's and DEC's NFS mountd do this (at least nfsbug 
says they are mountable).  If the last line of your /etc/hosts is a machine 
which you export files to then this allows any remote machine on the net to 
mount those file-systems.

The fact that this happens suggests that maybe mountd isn't checking the name 
it gets back from the gethostbyaddr() also maps forwards by a gethostbyname(). 
 However, a trivial check shows that altering a PTR RR to a name which is in 
an exports list doesn't get you access. The mountd probably checks that the 
official name is correct but doesn't bother checking the aliases.

Lots of other things may also trust the results of gethostbyaddr() but I've 
not fallen over them yet.

Fortunately there is a simple fix -- just add a dummy line with no aliases to 
the end of your /etc/hosts file, the following appears to work for me:

# Dummy entry to work round bug in gethostbyaddr() on HP/DEC
127.0.0.1        GARBAGENAME

On the HP, at least, you have to restart rpc.mountd as it seems to cache the 
results of gethostbyname() (or maybe the corruption already happened elsewhere 
in it's tables).

On HPs also apply patch PHNE_4879 which fixes (along with lots of NFS/NIS 
things) the problem of the portmapper passing on requests to the mountd.

To test your systems the following trivial piece of code:

--cut-here--res.c--
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

main(argc, argv)
int argc ;
char *argv[] ;
{
  char *host, **aliases ;
  struct hostent *hp ;
  int i, addr ;

  for (i = 1; i < argc; ++i) {
    host = argv[i] ;

    /* hosts can either be symbolic names or real IP addresses */
    if (isdigit(*host)) {
      addr = inet_addr(host);
      hp = gethostbyaddr((char *)&addr, 4, AF_INET) ;
    } else {
      hp = gethostbyname(host);
    }
    if (hp == NULL) {
      fprintf(stderr, "%s: unknown host\n", host);
    } else {
      printf("Canonical name %s\n", hp->h_name) ;
      aliases = hp->h_aliases ;
      if (*aliases == NULL)
	printf("no aliases\n") ;
      else {
	printf("aliases: \n") ;
	while (*aliases) {
	  printf("  %s\n", *aliases) ;
	  aliases++ ;
	}
      }
    }
  }
}
      
--cut-here--res.c--

Run it with the IP address of a machine not in your hosts files, and see if it 
lists any strange aliases.  With the extra line in /etc/hosts you should see 
no aliases at all.

Since I doubt that DEC and HP share many programmers I'd guess that the buggy 
gethostbyaddr() code came from elsewhere.  It may well be that this bug exists 
in lots of other systems out there and they may be vulnerable.

Note that this bug isn't present in gethostbyname() as far as I can tell.

  -- Jon Peatfield  (DAMTP, unix network admin)

Jon Peatfield, Computer Officer, the DAMTP, University of Cambridge
Telephone: (+44 223) 3-37852     Mail: J.S.Peatfield@damtp.cam.ac.uk